using Microsoft.Phone.Controls.Maps.AutomationPeers;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Shapes;
namespace Microsoft.Phone.Controls.Maps.Core
{
	[ContentProperty("Content"), TemplatePart(Name = "EmbeddedShape", Type = typeof(Shape)), TemplatePart(Name = "ContentGrid", Type = typeof(Grid))]
	public abstract class MapShapeBase : ContentControl, IProjectable
	{
		internal const string ContentGridElementName = "ContentGrid";
		internal const string EmbeddedShapeElementName = "EmbeddedShape";
		private Grid contentGrid;
		private ProjectionUpdateLevel pendingUpdate = ProjectionUpdateLevel.Full;
		private Shape shape;
		private Point topLeftViewportPoint;
		private static readonly DependencyProperty LocationsProperty = DependencyProperty.Register("Locations", typeof(LocationCollection), typeof(MapShapeBase), new PropertyMetadata(new PropertyChangedCallback(MapShapeBase.Locations_Changed)));
		public Brush Fill
		{
			get
			{
				return this.EmbeddedShape.get_Fill();
			}
			set
			{
				if (this.EmbeddedShape != null)
				{
					this.EmbeddedShape.set_Fill(value);
				}
			}
		}
		public Brush Stroke
		{
			get
			{
				return this.EmbeddedShape.get_Stroke();
			}
			set
			{
				if (this.EmbeddedShape != null)
				{
					this.EmbeddedShape.set_Stroke(value);
				}
			}
		}
		public double StrokeThickness
		{
			get
			{
				return this.EmbeddedShape.get_StrokeThickness();
			}
			set
			{
				if (this.EmbeddedShape != null)
				{
					this.EmbeddedShape.set_StrokeThickness(value);
				}
			}
		}
		public DoubleCollection StrokeDashArray
		{
			get
			{
				return this.EmbeddedShape.get_StrokeDashArray();
			}
			set
			{
				if (this.EmbeddedShape != null)
				{
					this.EmbeddedShape.set_StrokeDashArray(value);
				}
			}
		}
		public PenLineCap StrokeDashCap
		{
			get
			{
				return this.EmbeddedShape.get_StrokeDashCap();
			}
			set
			{
				if (this.EmbeddedShape != null)
				{
					this.EmbeddedShape.set_StrokeDashCap(value);
				}
			}
		}
		public double StrokeDashOffset
		{
			get
			{
				return this.EmbeddedShape.get_StrokeDashOffset();
			}
			set
			{
				if (this.EmbeddedShape != null)
				{
					this.EmbeddedShape.set_StrokeDashOffset(value);
				}
			}
		}
		public PenLineCap StrokeEndLineCap
		{
			get
			{
				return this.EmbeddedShape.get_StrokeEndLineCap();
			}
			set
			{
				if (this.EmbeddedShape != null)
				{
					this.EmbeddedShape.set_StrokeEndLineCap(value);
				}
			}
		}
		public PenLineJoin StrokeLineJoin
		{
			get
			{
				return this.EmbeddedShape.get_StrokeLineJoin();
			}
			set
			{
				if (this.EmbeddedShape != null)
				{
					this.EmbeddedShape.set_StrokeLineJoin(value);
				}
			}
		}
		public double StrokeMiterLimit
		{
			get
			{
				return this.EmbeddedShape.get_StrokeMiterLimit();
			}
			set
			{
				if (this.EmbeddedShape != null)
				{
					this.EmbeddedShape.set_StrokeMiterLimit(value);
				}
			}
		}
		public PenLineCap StrokeStartLineCap
		{
			get
			{
				return this.EmbeddedShape.get_StrokeStartLineCap();
			}
			set
			{
				if (this.EmbeddedShape != null)
				{
					this.EmbeddedShape.set_StrokeStartLineCap(value);
				}
			}
		}
		public LocationCollection Locations
		{
			get
			{
				return (LocationCollection)base.GetValue(MapShapeBase.LocationsProperty);
			}
			set
			{
				base.SetValue(MapShapeBase.LocationsProperty, value);
			}
		}
		protected abstract PointCollection ProjectedPoints
		{
			get;
			set;
		}
		protected Shape EmbeddedShape
		{
			get
			{
				return this.shape;
			}
			set
			{
				if (value != null)
				{
					this.SetEmbeddedShape(value);
				}
			}
		}
		public MapBase ParentMap
		{
			get
			{
				IProjectable projectable = base.get_Parent() as IProjectable;
				if (projectable == null)
				{
					ContentPresenter contentPresenter = VisualTreeHelper.GetParent(this) as ContentPresenter;
					if (contentPresenter != null)
					{
						projectable = (VisualTreeHelper.GetParent(contentPresenter) as IProjectable);
					}
				}
				if (projectable != null)
				{
					return projectable.ParentMap;
				}
				return null;
			}
		}
		protected MapShapeBase()
		{
			base.set_UseLayoutRounding(false);
			this.contentGrid = new Grid();
		}
		private static void Locations_Changed(DependencyObject o, DependencyPropertyChangedEventArgs ea)
		{
			MapShapeBase mapShapeBase = o as MapShapeBase;
			if (mapShapeBase != null)
			{
				LocationCollection locationCollection = ea.get_OldValue() as LocationCollection;
				if (locationCollection != null)
				{
					locationCollection.remove_CollectionChanged(new NotifyCollectionChangedEventHandler(mapShapeBase.Locations_CollectionChanged));
				}
				LocationCollection locationCollection2 = ea.get_NewValue() as LocationCollection;
				if (locationCollection2 != null)
				{
					locationCollection2.add_CollectionChanged(new NotifyCollectionChangedEventHandler(mapShapeBase.Locations_CollectionChanged));
				}
				mapShapeBase.ProjectionUpdated(ProjectionUpdateLevel.Full);
			}
		}
		private void Locations_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
		{
			this.ProjectionUpdated(ProjectionUpdateLevel.Full);
		}
		protected virtual void SetEmbeddedShape(Shape newShape)
		{
			if (this.shape != null)
			{
				newShape.set_Fill(this.shape.get_Fill());
				newShape.set_Stroke(this.shape.get_Stroke());
				newShape.set_StrokeThickness(this.shape.get_StrokeThickness());
				using (IEnumerator<double> enumerator = this.shape.get_StrokeDashArray().GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						double num = enumerator.get_Current();
						newShape.get_StrokeDashArray().Add(num);
					}
				}
				newShape.set_StrokeDashCap(this.shape.get_StrokeDashCap());
				newShape.set_StrokeDashOffset(this.shape.get_StrokeDashOffset());
				newShape.set_StrokeEndLineCap(this.shape.get_StrokeEndLineCap());
				newShape.set_StrokeLineJoin(this.shape.get_StrokeLineJoin());
				newShape.set_StrokeMiterLimit(this.shape.get_StrokeMiterLimit());
				newShape.set_StrokeStartLineCap(this.shape.get_StrokeStartLineCap());
			}
			else
			{
				this.contentGrid.get_Children().Add(newShape);
			}
			this.shape = newShape;
		}
		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();
			this.contentGrid = (base.GetTemplateChild("ContentGrid") as Grid);
			this.EmbeddedShape = (base.GetTemplateChild("EmbeddedShape") as Shape);
			if (this.contentGrid != null)
			{
				this.contentGrid.set_UseLayoutRounding(base.get_UseLayoutRounding());
			}
		}
		public void ProjectionUpdated(ProjectionUpdateLevel updateLevel)
		{
			if (updateLevel != ProjectionUpdateLevel.None)
			{
				base.InvalidateMeasure();
				base.InvalidateArrange();
				this.pendingUpdate |= updateLevel;
			}
		}
		protected override Size MeasureOverride(Size availableSize)
		{
			MapBase parentMap = this.ParentMap;
			if (this.pendingUpdate != ProjectionUpdateLevel.None && parentMap != null)
			{
				if (this.Locations != null)
				{
					if (this.pendingUpdate == ProjectionUpdateLevel.Full && this.Locations.get_Count() > 0)
					{
						PointCollection pointCollection = new PointCollection();
						Point point = new Point(1.7976931348623157E+308, 1.7976931348623157E+308);
						IEnumerable<Point> enumerable = parentMap.Mode.LocationToViewportPoint(this.Locations);
						using (IEnumerator<Point> enumerator = enumerable.GetEnumerator())
						{
							while (enumerator.MoveNext())
							{
								Point current = enumerator.get_Current();
								point.set_X(Math.Min(point.get_X(), current.get_X()));
								point.set_Y(Math.Min(point.get_Y(), current.get_Y()));
								pointCollection.Add(current);
							}
						}
						for (int i = 0; i < pointCollection.get_Count(); i++)
						{
							pointCollection.set_Item(i, new Point(pointCollection.get_Item(i).get_X() - point.get_X(), pointCollection.get_Item(i).get_Y() - point.get_Y()));
						}
						this.ProjectedPoints = pointCollection;
					}
					Point point2;
					if (this.ProjectedPoints.get_Count() > 0 && this.Locations.get_Count() > 0 && parentMap.TryLocationToViewportPoint(this.Locations.get_Item(0), out point2))
					{
						this.topLeftViewportPoint = new Point(point2.get_X() - this.ProjectedPoints.get_Item(0).get_X(), point2.get_Y() - this.ProjectedPoints.get_Item(0).get_Y());
					}
				}
				else
				{
					this.ProjectedPoints.Clear();
				}
				this.pendingUpdate = ProjectionUpdateLevel.None;
			}
			this.contentGrid.Measure(new Size(1.7976931348623157E+308, 1.7976931348623157E+308));
			if (parentMap == null)
			{
				return new Size(0.0, 0.0);
			}
			return parentMap.ViewportSize;
		}
		protected override Size ArrangeOverride(Size finalSize)
		{
			this.contentGrid.Arrange(new Rect(this.topLeftViewportPoint.get_X(), this.topLeftViewportPoint.get_Y(), this.contentGrid.get_DesiredSize().get_Width() + 1.0, this.contentGrid.get_DesiredSize().get_Height() + 1.0));
			MapBase parentMap = this.ParentMap;
			if (parentMap == null)
			{
				return new Size(0.0, 0.0);
			}
			return parentMap.ViewportSize;
		}
		protected override AutomationPeer OnCreateAutomationPeer()
		{
			return new BaseAutomationPeer(this, "MapShape");
		}
	}
}
